
import { TreeItem, TreeDataProvider, TreeItemCollapsibleState, CancellationToken, ProviderResult } from 'vscode';
import * as vscode from 'vscode';
import configUtils from '../utils/ConfigUtils';
import webView from './webView';
import { tomcatUtils } from '../utils/OperationUtils';
import fileUtils from '../utils/fileUtils';

enum Operation {
  addServer = 'addServer',
  startServer = 'startServer',
  stopServer = 'stopServer',
  addDeploy = 'addDeploy',
  server = 'server',
  package = 'package',
  delete = 'deleteServer'
}

class Node extends TreeItem {
  data: string | null;
  operation: Operation | null = null;
  children: Node[] = [];
  constructor(
    public label: string,
    public collapsibleState: TreeItemCollapsibleState = TreeItemCollapsibleState.None,
    children: Node[] = [],
    data: any = null,
    operation: Operation | null = null
  ) {
    super(label);
    this.data = data;
    this.operation = operation;
    this.children = children;
    if(children.length > 0) {
      this.collapsibleState = TreeItemCollapsibleState.Collapsed;
    }
  }

  addChildren(...childNodes: Node[]) {
    this.collapsibleState = TreeItemCollapsibleState.Collapsed;
    this.children.push(...childNodes);
  }
}

export class TreeView implements TreeDataProvider<Node> {
  private _onDidChangeTreeData: vscode.EventEmitter<Node | undefined | null | void> = new vscode.EventEmitter<Node | undefined | null | void>();
  readonly onDidChangeTreeData: vscode.Event<Node | undefined | null | void> = this._onDidChangeTreeData.event;

  node: Node[] = [];
  constructor(...node: Node[]) {
    this.node = node;
  }
  addNode(...node: Node[]) {
    this.node.push(...node);
  }
  getChildren(element?: Node | undefined): ProviderResult<Node[]> {
    if (!element) {
      return this.node;
    }
    return element.children;
  }

  resolveTreeItem?(item: TreeItem, element: Node, token: CancellationToken): ProviderResult<TreeItem> {
    return element;
  }

  getTreeItem(element: Node): TreeItem {
    if (element.operation === Operation.server) {
      element.contextValue = "openTomcatFile";
    } else {
      element.command = {
        command: 'tomcat-hot.treeCommand',
        title: 'My Command',
        tooltip: 'My Command',
        arguments: [element]
      };
    }
    return element;
  }

  refresh(): void {
    this._onDidChangeTreeData.fire();
  }
}

class TomcatHotTreeView {
  commands: any = commands;
  treeview = new TreeView();
  context?: vscode.ExtensionContext;
  init(context: vscode.ExtensionContext) {
    this.context = context;
  }

  getServer(serverView: Node) {
    let context = this.context;
    if (context === undefined) {
      return;
    }
    let configure = configUtils.getConfig();
    Object.keys(configure['server']).forEach((key: string) => {
      let start = new Node("start", TreeItemCollapsibleState.None, [], key, Operation.startServer);
      start.iconPath = vscode.Uri.file(context.extensionPath + "/icons/start.svg");
      let stop = new Node("stop", TreeItemCollapsibleState.None, [], key, Operation.stopServer);
      stop.iconPath = vscode.Uri.file(context.extensionPath + "/icons/stop.svg");
      let del = new Node("delete", TreeItemCollapsibleState.None, [], key, Operation.delete);
      del.iconPath = vscode.Uri.file(context.extensionPath + "/icons/delete.svg");
      let tomcat = new Node(key, TreeItemCollapsibleState.None, [start, stop, del], key, Operation.server);
      tomcat.iconPath = vscode.Uri.file(context.extensionPath + "/icons/icons8.svg");
      serverView.addChildren(tomcat);
    });
  }

  getDevelop(developParent: Node) {
    let context = this.context;
    if (context === undefined) {
      return;
    }
    let configure = configUtils.getConfig();
    Object.keys(configure['develop']).forEach((key: string) => {
      let isLoad = configure['develop'][key]['load'];
      let nodeData = configure['develop'][key];
      nodeData['name'] = key;
      nodeData['lastName'] = key;
      isLoad = isLoad !== null && isLoad !== undefined && isLoad ? true : false;
      // 应用
      let app = new Node(key, TreeItemCollapsibleState.None, [], nodeData, Operation.package);
      app.contextValue = 'editDevelop';
      app.iconPath = vscode.Uri.file(context.extensionPath + (isLoad ? "/icons/box-green.svg" : "/icons/box.svg"));

      // 部署
      let dev = new Node("装载", TreeItemCollapsibleState.None, [], key, Operation.delete);
      dev.iconPath = vscode.Uri.file(context.extensionPath + "/icons/install.svg");
      app.addChildren(dev);

      // 部署
      let undev = new Node("卸载", TreeItemCollapsibleState.None, [], key, Operation.delete);
      undev.iconPath = vscode.Uri.file(context.extensionPath + "/icons/uninstall.svg");
      app.addChildren(undev);

      // 删除应用
      let delDevelop = new Node("删除", TreeItemCollapsibleState.None, [], key, Operation.delete);
      delDevelop.iconPath = vscode.Uri.file(context.extensionPath + "/icons/delete.svg");
      app.addChildren(delDevelop);

      developParent.addChildren(app);
    });
  }

  flush() {
    let context = this.context;
    if (context === undefined) {
      return;
    }
    configUtils.flush();
    this.treeview.node = [];

    // 应用部署
    let develop = new Node("应用列表", TreeItemCollapsibleState.None, []);
    develop.iconPath = vscode.Uri.file(context.extensionPath + "/icons/box.svg");
    develop.contextValue = "develop";

    const add = new Node("服务器列表", TreeItemCollapsibleState.None, [], 'add', Operation.addServer);
    add.iconPath = vscode.Uri.file(context.extensionPath + "/icons/icons8.svg");
    add.contextValue = "addTomcat";

    this.treeview.addNode(add, develop);
    this.getDevelop(develop);
    this.getServer(add);
    this.treeview.refresh();
  }

  // treeview 点击事件
  command(element: Node) {
    switch (element.operation) {
      case Operation.server: {
        let server = configUtils.getConfig()['server'][element.data ?? ""];
        server['name'] = element.data;
        server['type'] = 'change';
        server['deleteName'] = element.data;
        let init = `config=${JSON.stringify(server)}`;
        webView.getWebview("tomcat.html", init);
        console.log(element.data);
        break;
      }
      case Operation.startServer: {
        if (element.data === undefined || element.data === null) {
          return;
        }
        let path = configUtils.getConfig()['server'][element.data]['installPath'];
        let javaExec = configUtils.getConfig()['server'][element.data]['javaExec'];
        tomcatUtils.startTomcat(element.data, path, path, javaExec);
        break;
      }
      case Operation.stopServer: {
        if (element.data === undefined || element.data === null) {
          return;
        }
        tomcatUtils.stopTomcat(element.data);
        break;
      }
      case Operation.addDeploy: {
        tomcatHotTreeView.flush();
        break;
      }
      case Operation.delete: {
        if (element.data !== null) {
          configUtils.removeServer(element.data);
          webView.close();
          tomcatHotTreeView.flush();
        }
        break;
      }
    }
  }
}

// treeview 右键菜单事件
let commands = {
  editTomcat(node: Node) {
    let config = configUtils.getConfig()['server'][node.label];
    let server = { "name": node.label, type: "change", "deleteName": node.label, ...config };
    webView.getWebview("tomcat.html", server);
  },
  async openServerXmlFile(node: Node, ) {
    if(node === null || node === undefined){
      return;
    }
    vscode.window.showOpenDialog(<vscode.OpenDialogOptions>{
        canSelectFiles: true,
        canSelectFolders: false,
        defaultUri: vscode.Uri.file(configUtils.getConfig()['server'][node.label]['installPath'] + "/conf"),
        openLabel: "打开"
      }).then( (data: vscode.Uri[] | undefined) => {
        if (data?.length !== 1) {
          return;
        } else {
          vscode.workspace.openTextDocument(data[0]).then((context)=>{
            vscode.window.showTextDocument(context);
          });
          
        }
      });

  },
  async addTomcat(node: Node) {
    // 拉起tomcat
    webView.getWebview("tomcat.html");
  },
  async addDevelop() {
    // 拉起tomcat
    webView.getWebview("develop.html");
  },
  async editDevelop(node: Node){
    webView.getWebview("develop.html", node.data);
  }
};

const tomcatHotTreeView = new TomcatHotTreeView();

export default tomcatHotTreeView;
